/**
**************************************************************************************
*Palisma - Secrets of the Illuminati is an open-source 2D RPG                        *
*Copyright (C) 2006, Tony Sparks                                                     *
*                                                                                    *
*This library is free software; you can redistribute it and/or                       *
*modify it under the terms of the GNU Lesser General Public                          *
*License as published by the Free Software Foundation; either                        *
*version 2.1 of the License, or (at your option) any later version.                  *
*                                                                                    *
*This library is distributed in the hope that it will be useful,                     *
*but WITHOUT ANY WARRANTY; without even the implied warranty of                      *
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                   *
*Lesser General Public License for more details.                                     *
*                                                                                    *
*You should have received a copy of the GNU Lesser General Public                    *
*License along with this library; if not, write to the Free Software                 *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA      *
**************************************************************************************
*/
#pragma once

#include <string>
#include <vector>
#include <algorithm>

#include "SoundSource.h"
#include "SoundLoader.h"

#include "../IProcess.h"
#include "../Commands.h"
/**
========================
The Sound System Interface
========================
*/
class ISound : public IProcess
{
public:
	/** Initialize the subsystem */
	virtual int Init()=0;
	/** Update with time elapsed */
	virtual void Update(float deltaTime)=0; 
	/** Close off the system */
	virtual void Shutdown()=0;

    /** Load a sound into the cache */
    SoundSource* LoadSound(const std::string &path) {
        SoundSource* sound = m_loader.LoadSound( path );
        if ( sound )
            AddSound( sound );
        return sound;
    };

    /** Test for a sound */
    bool HasSound(SoundSource* sound) const {
        return m_loader.HasSound(sound);
    }
	/** Add a sound to the sound list of objects to 
	 *  be played
	 */
	void AddSound(SoundSource* sound) { 
        if ( std::find(m_sounds.begin(), m_sounds.end(), sound ) == m_sounds.end() )
            m_sounds.push_back(sound); 
    };
	/** Remove a sound from the sound list */
	void RemoveSound(SoundSource* sound) { 
        // delete from both lists
        m_loader.Delete( sound );
		for(std::vector<SoundSource*>::iterator i =m_sounds.begin();i != m_sounds.end(); i++)
		{
			if ( (*i) == sound ) {
				m_sounds.erase( i );
				return;
			}
		}

	};

	/** Remove all Sounds */
	void RemoveAll() { 
		m_sounds.clear();
        m_loader.Clear();
	};

	/** Mute all sounds */
	virtual void Mute( bool b )=0;
	/** Check to see if all sounds are Mute */
	bool IsMute() const { return m_mute; };

    /** How many sounds are in the resource cache */
    size_t NumSounds() const { return m_loader.NumSounds(); };

	/** Set the Volume of all sounds 
	 *  0 - 1.0
	 */
	virtual void SetVolume(float v)=0;
	/** Retrieve the volume */
	float GetVolume() const { return m_volume; };

    /** Set Music volume */
    void MusicVolume( float v ) { 
        if ( m_music )
            m_music->Volume( v );
        m_mvolume = v;
    };
    /** Get the Music Volume */
    float GetMusicVolume() const { return m_mvolume; };
	/** Play a music file */
	virtual void PlayMusic( const std::string &file )=0; 
	/** Stop the current Music */
	virtual void StopMusic()=0;
	/** Resume the Music */
	virtual void ResumeMusic()=0;
    /** Stop all the sounds */
    virtual void StopAll()=0;
    /** Resume all the sounds */
    virtual void ResumeAll()=0;

protected:	
	
	std::vector<SoundSource*>   m_sounds;         // list of sounds
	
    // the SoundLoader
    SoundLoader m_loader;

	// Muted
	bool m_mute;
	// main volume
	float m_volume;

    // music volume
    float m_mvolume;

	// Music sound
	SoundSource* m_music;


public:
	virtual ~ISound(void){};
};


/**
=======================
Stop a sound through the console
=======================
*/
class Stop_f : public ICommand
{
public:
    Stop_f() : m_soundSys( NULL )  { };
    /** Set the Sound System */
    void Set( ISound* s ) { m_soundSys = s; };
	/** stop a sound through the console */
	void Exec(std::string &s);
	virtual ~Stop_f() {};

private:
    ISound*     m_soundSys;
};
/**
=======================
Play a sound through the console
=======================
*/
class Play_f : public ICommand
{
public:
	Play_f() : m_soundSys( NULL ) { m_sound = NULL; };
    /** Set the Sound System */
    void Set( ISound* s ) { m_soundSys = s; };
	/** Play a sound through the console */
	void Exec(std::string &s);
	virtual ~Play_f() {};

private:
    ISound*         m_soundSys;
    SoundSource*    m_sound;
};

/**
=======================
Resume a sound through the console
=======================
*/
class Resume_f : public ICommand
{
public:
	Resume_f() : m_soundSys( NULL ) { };
    /** Set the Sound System */
    void Set( ISound* s ) { m_soundSys = s; };
	/** Resume a sound through the console */
	void Exec(std::string &s);
	virtual ~Resume_f() {};

private:
    ISound*     m_soundSys;
};


/**
==========================
Dump all sounds from memory
==========================
*/
class S_dump_f : public ICommand
{
public:
	S_dump_f() : m_soundSys( NULL ) { };
    /** Set the Sound System */
    void Set( ISound* s ) { m_soundSys = s; };
	/** Dump all sounds through the console */
    void Exec(std::string &s);
	virtual ~S_dump_f() {};

private:
    ISound*     m_soundSys;
};

